﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SIGEB.Prototipo.Control;
using System.Collections;
using SIGEB.Modelo.moduloTipoDocumentos;
using SIGEB.Modelo;
using SIGEB.Modelo.moduloPerfiles;

namespace SIGEB.Prototipo.Vista.moduloTipoDocumentos
{
    public partial class frm_TipoDocumento : frm_IMEC
    {
        #region "constructores"

        public frm_TipoDocumento()
        {
            InitializeComponent();
            inicializarComponentes();
        }

        public frm_TipoDocumento(controlPrincipal cp):base(cp)
        {
            InitializeComponent();
            asignarUI(this.Controls);
            inicializarComponentes();
        }

        private void inicializarComponentes()
        {
            cargarTiposAtributo();
            base.dgv_busqueda = dgv_tipoDocs;
            cargarTiposAtributo();
        }


        #endregion

        #region "eventos"

        private void btn_agregarCondicion_Click(object sender, EventArgs e)
        {
            cp.abrirVentana(this, controlPrincipal.VENTANA_CONDICIONES, null);
        }

        private void txb_busqueda_TextChanged(object sender, EventArgs e)
        {
            lbl_mensajes.Text = string.Empty;
        }

        private void txb_busqueda_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode.Equals(Keys.Enter))
            {
                if (txb_busqueda.Text.Equals(string.Empty))
                {
                    if (modoB)
                    {
                        modoB = false;
                        finalizarBusqueda();
                    }
                }
                else
                {
                    modoB = true;
                    string[] v = new string[] { "columna1" };
                    if (iniciarBusqueda(txb_busqueda.Text, v).Equals(0))
                    {
                        mostrarInfo("La búsqueda no generó ningún resultado.");
                        modoB = false;
                        finalizarBusqueda();
                    }
                }
            }
        }

        private void txt_nombreTipoDoc_TextChanged(object sender, EventArgs e)
        {
            //borrarError(txt_nombreTipoDoc);
            //lbl_mensajes.Text = string.Empty;
        }

        private void txt_nomAtributo_TextChanged(object sender, EventArgs e)
        {
            //borrarError(txt_nomAtributo);
            //lbl_mensajes.Text = string.Empty;
        }

        private void cmb_tipoDato_SelectedIndexChanged(object sender, EventArgs e)
        {
            //borrarError(cmb_tipoDato);
            //lbl_mensajes.Text = string.Empty;
        }

        /// <summary>
        /// se llama cuando se realiza una actualización de la base de datos
        /// en esta misma instancia
        /// </summary>
        /// <param name="referencia"></param>
        /// <param name="e"></param>
        public override void actualizar(object referencia, bibliotecaObservador.EventoActualizacion e)
        {
            int numConjunto = (int)referencia;
            if (numConjunto == conjuntoBase.CONJTIPODOCS)
            {
                cargarDatosTipoDocumento();
            }
            else if (numConjunto == conjuntoBase.CONJATRIBUTOS)
            {
                try
                {
                    tipoDocActual = cp.ctrlTipoDoc.obtenerTipoDocumento(tipoDocActual.codTipoDocumento);
                }
                catch (Exception ex)
                {
                    ventanaError(ex.Message);
                }
                escribirTipoDocumento();
            }
        }

        private void cargarTiposAtributo()
        {
            cmb_tipoDato.Items.Clear();
            cmb_tipoDato.Items.Add(new comboBoxItem(atributo.ALFANUMERICO.ToString(), "Alfa-Numérico"));
            cmb_tipoDato.Items.Add(new comboBoxItem(atributo.NUMERO.ToString(), "Número"));
            cmb_tipoDato.Items.Add(new comboBoxItem(atributo.FECHA.ToString(), "Fecha"));
        }

        private void cargarDatosTipoDocumento()
        {
            try
            {
                datosActuales = cp.ctrlTipoDoc.obtenerTiposDocumento();
                llenarDTGTipoDoc(datosActuales);
            }
            catch (Exception ex)
            {
                ventanaError(ex.Message);
            }

        }

        /// <summary>
        /// se llama cada vez que se abre la ventana y recibe
        /// los parámetros
        /// </summary>
        /// <param name="arg">se usa para que se le pase cualquier tipo de objeto al abrir la ventana</param>
        public override void hacerVisible(object[] arg)
        {
            base.hacerVisible(arg);
            if (arg == null)
            {
                cargarDatosTipoDocumento();
            }
            PasarConsulta();
            actualizaControles();


        }

        /// <summary>
        /// se activa cuando se selecciona alguna fila del DGV
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dgv_listado_SelectionChanged(object sender, EventArgs e)
        {
            if (estado.CONSULTANDO())
            {
                tipoDocActual = getSelected();
                escribirTipoDocumento();
            }
            actualizaControles();
        }

        private void dgv_atributos_SelectionChanged(object sender, EventArgs e)
        {
            actualizarSeleccionAtributo();
        }

        #endregion

        #region "validación"

        #endregion

        #region "captura"


        /// <summary>
        /// obtiene un tipoUsuario creado con los campos de texto y combo box que hayan en el momento
        /// </summary>
        /// <returns></returns>
        private tipoDocumento getFromFields()
        {
            return new tipoDocumento(null, txt_nombreTipoDoc.Text, null);
        }

        /// <summary>
        /// obtieneel tipoUsuario que se seleccionó del DGV
        /// </summary>
        /// <returns></returns>
        private tipoDocumento getSelected()
        {
            tipoDocumento nuevo = null;
            try
            {
                dgv_tipoDocs.Rows[dgv_tipoDocs.SelectedCells[0].RowIndex].Selected = true;
                String codigo = dgv_tipoDocs.SelectedRows[0].Cells[0].Value.ToString();
                if (codigo != null)
                {
                    nuevo = getTipoDocumento(codigo);
                    if (nuevo != null)
                    {
                        tipoDocActual = nuevo;
                    }
                }
            }
            catch
            {

            }
            return nuevo;
        }

        private atributo getAtributoSelected()
        {
            try
            {
                dgv_atributos.Rows[dgv_atributos.SelectedCells[0].RowIndex].Selected = true;
                String codigo = dgv_atributos.SelectedRows[0].Cells[0].Value.ToString();
                if (codigo != null && codigo != "" && tipoDocActual != null)
                {
                    return getAtributo(tipoDocActual.atributos, codigo);
                }
            }
            catch 
            {
                return null;
            }
            return null;
        }

        /// <summary>
        /// obtiene un tipoUsuario entre la lista de datosActuales
        /// </summary>
        /// <param name="codigo"></param>
        /// <returns></returns>
        private tipoDocumento getTipoDocumento(String codigo)
        {
            if (datosActuales != null)
            {
                foreach (tipoDocumento act in datosActuales)
                {
                    if (act.codTipoDocumento == codigo)
                    {
                        return act;
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// obtene el atributo con el codigo de acuerdo con la lista atributos
        /// </summary>
        /// <param name="atributos"></param>
        /// <param name="codigo"></param>
        /// <returns></returns>
        private atributo getAtributo(LinkedList<atributo> atributos, String codigo)
        {
            if (atributos != null && codigo != null)
            {
                foreach (atributo act in atributos)
                {
                    if (act.codAtributo == codigo)
                    {
                        return act;
                    }
                }
            }
            return null;
        }

        #endregion

        #region "métodos"

        private void actualizarSeleccionAtributo()
        {
            atributo act = getAtributoSelected();
            if (estado.CONSULTANDO() && act != null)
            {
                escribirAtributo(act);
            }
            else
            {

                limpiarCamposAtributos();
            }
        }

        private void seleccionarTipoAtributo(int tipo)
        {
            string t = tipo.ToString();
            cmb_tipoDato.Text = "";
            foreach (object act in cmb_tipoDato.Items)
            {
                if (((comboBoxItem)act).id == t)
                {
                    cmb_tipoDato.Text = ((comboBoxItem)act).mostrar;
                    break;
                }
            }
        }

        private int getTipoAtributoSelected()
        {
            try
            {
                return int.Parse(((comboBoxItem)cmb_tipoDato.SelectedItem).id);
            }
            catch
            {
                return -1;
            }
        }

        private void escribirAtributo(atributo a)
        {
            if (a != null)
            {
                txt_nomAtributo.Text = a.nombre;
                cbx_indizable.Checked = a.indizable;
                seleccionarTipoAtributo(a.tipo);
            }
            else
            {
                limpiarCamposAtributos();
            }
        }

        private void limpiarCamposAtributos()
        {
            cmb_tipoDato.Text = "";
            cmb_tipoDato.SelectedItem = null;
            txt_nomAtributo.Text = "";
            cbx_indizable.Checked = false;
        }

        /// <summary>
        /// escribe tipoDocActual en los campos de texto
        /// </summary>
        private void escribirTipoDocumento()
        {
            if (tipoDocActual != null)
            {
                txt_nombreTipoDoc.Text = tipoDocActual.nombre;
                llenarAtributos(tipoDocActual.atributos);
            }
            else
            {
                limpiarCampos();
            }
        }

        /// <summary>
        /// lista en el ComboBox la lista que reciba por parámetro.
        /// Solamente listará los nombres del tipoPerfil
        /// </summary>
        /// <param name="atributos"></param>
        private void llenarAtributos(LinkedList<atributo> atributos)
        {
            llenarColumnasAtributos();
            if (atributos != null)
            {
                foreach (atributo act in atributos)
                {
                    dgv_atributos.Rows.Add(act.codAtributo, act.nombre, tipoAtributo(act.tipo));
                }
            }
        }

        private string tipoAtributo(int a)
        {
            if (a == atributo.ALFANUMERICO)
            {
                return "Alfa-Numérico";
            }
            if (a == atributo.NUMERO)
            {
                return "Numérico";
            }
            if (a == atributo.FECHA)
            {
                return "Fecha";
            }
            return "Indefinido";
        }

        private void llenarColumnasAtributos()
        {
            dgv_atributos.Columns.Clear();
            dgv_atributos.Columns.Add("id", "IdAtributo");
            dgv_atributos.Columns[0].Visible = false;
            dgv_atributos.Columns.Add("Nombre", "Nombre");
            dgv_atributos.Columns.Add("Tipo", "Tipo");
        }

        /// <summary>
        /// llena las columnas de acuerdo con los campos del tipoPerfil
        /// </summary>
        private void llenarColumnas()
        {
            dgv_tipoDocs.Columns.Clear();
            dgv_tipoDocs.Columns.Add("columna0", "Id");
            dgv_tipoDocs.Columns[0].Visible = false;
            dgv_tipoDocs.Columns.Add("columna1", "Nombre");
        }

        /// <summary>
        /// lista en el DGV la lista de tipoDoc recibda
        /// </summary>
        /// <param name="tiposDocumento"></param>
        private void llenarDTGTipoDoc(LinkedList<tipoDocumento> tiposDocumento)
        {
            llenarColumnas();
            if (tiposDocumento != null)
            {
                foreach (tipoDocumento act in tiposDocumento)
                {
                    dgv_tipoDocs.Rows.Add(act.codTipoDocumento, act.nombre);
                }
            }
        }

        #endregion

        #region "controles"

        /// <summary>
        /// actualiza el estado de los botones de acuerdo con el estado que
        /// se encuentra la ventana(en modo consulta, edición o agregando nuevo)
        /// </summary>
        private void actualizarBotones()
        {
            if (estado.AGREGANDO())
            {
                btn_Nuevo.Enabled = false;
                btn_eliminar.Enabled = false;
                btn_guardar.Enabled = true;
                btn_editar.Enabled = false;
                btn_cancelar.Enabled = true;

                btn_agregarAtributo.Enabled = false;
                btn_agregarCondicion.Enabled = false;
                btn_EliminarAtributo.Enabled = false;
            }
            else if (estado.EDITANDO())
            {
                btn_Nuevo.Enabled = false;
                btn_eliminar.Enabled = true;
                btn_guardar.Enabled = true;
                btn_editar.Enabled = false;
                btn_cancelar.Enabled = true;

                btn_agregarAtributo.Enabled = true;
                btn_agregarCondicion.Enabled = true;
                btn_EliminarAtributo.Enabled = false;
            }
            else if (estado.CONSULTANDO())
            {
                btn_Nuevo.Enabled = true;
                btn_eliminar.Enabled = tipoDocActual != null;
                btn_guardar.Enabled = false;
                btn_editar.Enabled = tipoDocActual != null;
                btn_cancelar.Enabled = false;
                btn_agregarAtributo.Enabled = false;
                btn_agregarCondicion.Enabled = false;
                btn_EliminarAtributo.Enabled = true && getAtributoSelected() != null;
            }
        }

        /// <summary>
        /// actualiza el estado de los campos de texto y CBX de acuerdo con el estado que
        /// se encuentra la ventana(en modo consulta, edición o agregando nuevo)
        /// </summary>
        private void actualizarCampos()
        {
            borrarError(txt_nombreTipoDoc);
            borrarError(txt_nomAtributo);
            borrarError(cmb_tipoDato);
            lbl_mensajes.Text = string.Empty;

            if (estado.AGREGANDO())
            {
                txt_nombreTipoDoc.Enabled = true;
                txt_nomAtributo.Enabled = false;
                cbx_indizable.Enabled = false;
                cmb_tipoDato.Enabled = false;

                dgv_atributos.Enabled = false;
                dgv_tipoDocs.Enabled = false;
            }
            else if (estado.EDITANDO())
            {
                txt_nombreTipoDoc.Enabled = true;

                txt_nomAtributo.Enabled = true;
                cbx_indizable.Enabled = true;
                cmb_tipoDato.Enabled = true;

                dgv_atributos.Enabled = false;
                dgv_tipoDocs.Enabled = false;
            }
            else if (estado.CONSULTANDO())
            {
                txt_nombreTipoDoc.Enabled = false;

                txt_nomAtributo.Enabled = false;
                cbx_indizable.Enabled = false;
                cmb_tipoDato.Enabled = false;

                dgv_atributos.Enabled = true;
                dgv_tipoDocs.Enabled = true;
            }
        }

        /// <summary>
        /// actualiza el estado del tipoUsrActua en caso de que haya
        /// alguno seleccionado del DGV
        /// </summary>
        private void actualizartipoDocActual()
        {
            if (estado.CONSULTANDO() && tipoDocActual != null)
            {
                try
                {
                    tipoDocActual = cp.ctrlTipoDoc.obtenerTipoDocumento(tipoDocActual.codTipoDocumento);
                    escribirTipoDocumento();
                }
                catch (Exception ex)
                {
                    ventanaError(ex.Message);
                }
            }
        }

        /// <summary>
        /// actualiza los campos y los botones
        /// </summary>
        private void actualizaControles()
        {
            actualizarBotones();
            actualizarCampos();
            actualizartipoDocActual();
        }

        /// <summary>
        /// limpia los campos de texto
        /// </summary>
        private void limpiarCampos()
        {
            txt_nombreTipoDoc.Text = "";
        }

        #endregion

        #region "acciones"

        private void PasarAgregar()
        {
            if (estado.CONSULTANDO())
            {
                tipoDocActual = null;
                estado.agregar();
                actualizaControles();
                limpiarCampos();
            }
        }

        private void PasarConsulta()
        {
            bool modoConsulta = true;
            if (estado.AGREGANDO())
            {
                modoConsulta = confirmarOperacion("No se ha terminado de agregar el elemento");
            }
            else if (estado.EDITANDO())
            {
                modoConsulta = confirmarOperacion("Si continúa no se guardarán los cambios hechos");
            }
            if (modoConsulta)
            {
                estado.consultar();
                actualizaControles();
                if (tipoDocActual == null)
                {
                    limpiarCampos();
                }
                else
                {
                    escribirTipoDocumento();
                }
            }
        }

        private void PasarEditar()
        {
            if (estado.CONSULTANDO() && getSelected() != null && tipoDocActual != null)
            {
                estado.editar();
                actualizaControles();
                limpiarCamposAtributos();
            }
        }

        private void agregarNuevoTipoUsuario()
        {
            tipoDocumento nuevo = getFromFields();
            try
            {
                if (nuevo != null && cp.ctrlTipoDoc.camposAgregarValido(nuevo))
                {
                    cp.ctrlTipoDoc.agregarTipoDocumento(nuevo);
                    estado.consultar();
                    limpiarCampos();
                    actualizaControles();
                }
                else
                {
                    ventanaError("Algunos campos pueden estar incorrectos");
                }

            }
            catch (Exception e)
            {
                ventanaError(e.Message);
            }
        }

        private void agregarAtributo()
        {
            if (estado.EDITANDO() && tipoDocActual != null)
            {
                try
                {
                    if (cp.ctrlTipoDoc.camposAtrAgregarValido(tipoDocActual.codTipoDocumento, txt_nomAtributo.Text, cbx_indizable.Checked, getTipoAtributoSelected().ToString()))
                    {
                        cp.ctrlTipoDoc.agregarAtributo(tipoDocActual.codTipoDocumento, txt_nomAtributo.Text, cbx_indizable.Checked, getTipoAtributoSelected().ToString());
                        limpiarCamposAtributos();
                    }
                    else
                    {
                        throw new Exception("No se ha podido agregar el atributo nuevo");
                    }
                }
                catch(Exception e)
                {
                    ventanaError(e.Message);
                }
            }
        }

        private void eliminarAtributo()
        {
            if (estado.CONSULTANDO())
            {
                try
                {
                    atributo a = getAtributoSelected();
                    if (a != null)
                    {
                        cp.ctrlTipoDoc.elimiarAtributo(a.codAtributo);
                        actualizarSeleccionAtributo();
                    }
                }
                catch(Exception e)
                {
                    ventanaError(e.Message);
                }
            }
        }

        private void modificarTipoUsuario()
        {
            tipoDocumento nuevo = getFromFields();
            try
            {
                if (nuevo != null && tipoDocActual != null && cp.ctrlTipoDoc.campoModificarValido(tipoDocActual.codTipoDocumento,nuevo))
                {
                    cp.ctrlTipoDoc.modificarTipoDocumento(tipoDocActual.codTipoDocumento, nuevo);
                }
                estado.consultar();
                limpiarCampos();
                actualizaControles();
            }
            catch (Exception e)
            {
                ventanaError(e.Message);
            }
        }

        private void eliminarTipoUsuarioSelected()
        {
            try
            {
                if (estado.EDITANDO())
                {
                    cp.ctrlTipoDoc.eliminarTipoDocumento(tipoDocActual.codTipoDocumento);
                }
                else if (estado.CONSULTANDO() && tipoDocActual != null)
                {
                    cp.ctrlTipoDoc.eliminarTipoDocumento(tipoDocActual.codTipoDocumento);
                }
                PasarConsulta();
                limpiarCampos();
                limpiarCamposAtributos();
                actualizaControles();
            }
            catch (Exception ex)
            {
                ventanaError(ex.Message);
            }
        }

        #endregion

        #region "métodos botones"

        private void btn_Nuevo_Click(object sender, EventArgs e)
        {
            PasarAgregar();
        }

        private void btn_cancelar_Click(object sender, EventArgs e)
        {
            PasarConsulta();
        }

        private void btn_guardar_Click(object sender, EventArgs e)
        {
            if (txt_nombreTipoDoc.Text.Equals(string.Empty))
            {
                setError(txt_nombreTipoDoc, "Ingrese un nombre para el Tipo de Documento.");
            }
            else
            {
                borrarError(txt_nombreTipoDoc);
            }

            if(erp_error.GetError(txt_nombreTipoDoc).Equals(string.Empty))
            {
                if (estado.AGREGANDO())
                {
                    agregarNuevoTipoUsuario();
                }
                if (estado.EDITANDO())
                {
                    modificarTipoUsuario();
                }
            }
        }

        private void btn_editar_Click(object sender, EventArgs e)
        {
            PasarEditar();
        }

        private void btn_eliminar_Click(object sender, EventArgs e)
        {
            eliminarTipoUsuarioSelected();
        }

        private void btn_agregarAtributo_Click(object sender, EventArgs e)
        {
            if (txt_nomAtributo.Text.Equals(string.Empty))
            {
                setError(txt_nomAtributo, "Ingrese un nombre para el Atributo.");
            }
            else
            {
                borrarError(txt_nomAtributo);
            }
            if (cmb_tipoDato.SelectedIndex.Equals(-1))
            {
                setError(cmb_tipoDato, "Seleccione un tipo de dato para el Atributo.");
            }
            else
            {
                borrarError(cmb_tipoDato);
            }
            if(erp_error.GetError(txt_nomAtributo).Equals(string.Empty) && erp_error.GetError(cmb_tipoDato).Equals(string.Empty))
            {
                agregarAtributo();
            }
        }

        private void btn_EliminarAtributo_Click(object sender, EventArgs e)
        {
            eliminarAtributo();
        }

        #endregion

        #region "atributos"

        private LinkedList<tipoDocumento> datosActuales;
        private tipoDocumento tipoDocActual;

        #endregion
    }
}
